/* * Copyright (c) 2012. The Genome Analysis Centre, Norwich, UK * MISO project contacts: Robert Davey, Mario Caccamo @ TGAC * ********************************************************************* * * This file is part of MISO. * * MISO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MISO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MISO. If not, see <http://www.gnu.org/licenses/>. * * ********************************************************************* */ package uk.ac.bbsrc.tgac.miso.core.security; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.authentication.encoding.ShaPasswordEncoder; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.security.SignatureException; /** * A service class that encodes plaintext passwords into their hashed Base64-encoded counterparts * using a specified Spring Security PasswordEncoder * * @author Rob Davey * @since 0.0.2 */ public final class ShaPasswordCodecService implements PasswordCodecService { /** Field log */ protected static final Logger log = LoggerFactory.getLogger(ShaPasswordCodecService.class); /** Field instance */ private static ShaPasswordCodecService instance; private PasswordEncoder encoder; public PasswordEncoder getEncoder() { return encoder; } public void setEncoder(PasswordEncoder encoder) { this.encoder = encoder; } /** * Constructor PasswordCodecService creates a new PasswordCodecService instance with a SHA * password encoder as default */ private ShaPasswordCodecService() { encoder = new ShaPasswordEncoder(); } /** * Encrypt a plaintext String using a PasswordEncoder strategy, with a null salt. * * @param plaintext of type String * @return String the encrypted String of the given plaintext String */ public synchronized String encrypt(String plaintext) { return encrypt(plaintext, null); } /** * Encrypt a plaintext String using a PasswordEncoder strategy, with a given salt. * * @param plaintext of type String * @return String the encrypted String of the given plaintext String */ public synchronized String encrypt(String plaintext, byte[] salt) { return encoder.encodePassword(plaintext, salt); } /** * Encrypt a plaintext String using a hmac_sha1 salt * * @param key of type String * @param plaintext of type String * @return String the encrypted String of the given plaintext String * @throws java.security.SignatureException when the HMAC is unable to be generated */ public synchronized String encryptHMACSHA1(String key, String plaintext) throws SignatureException { String result; try { // get an hmac_sha1 key from the raw key bytes SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1"); // get an hmac_sha1 Mac instance and initialize with the signing key Mac mac = Mac.getInstance("HmacSHA1"); mac.init(signingKey); // compute the hmac on input data bytes byte[] rawHmac = mac.doFinal(plaintext.getBytes()); // base64-encode the hmac //result = new BASE64Encoder().encode(rawHmac); result = new Base64().encodeToString(rawHmac); } catch (Exception e) { throw new SignatureException("Failed to generate HMAC : " + e.getMessage()); } return result; } /** * Returns a singleton (as far as singletons are actually singletons!) instance of a PasswordCodecService object. * * @return PasswordCodecService instance. */ public static synchronized ShaPasswordCodecService getInstance() { if(instance == null) { instance = new ShaPasswordCodecService(); } return instance; } }